/*     */ package com.zimbra.cs.redolog;
/*     */ 
/*     */ import com.zimbra.common.util.FileUtil;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.LogFactory;
/*     */ import java.io.File;
/*     */ import java.io.FilenameFilter;
/*     */ import java.io.IOException;
/*     */ import java.text.DateFormat;
/*     */ import java.text.ParseException;
/*     */ import java.text.SimpleDateFormat;
/*     */ import java.util.Arrays;
/*     */ import java.util.Comparator;
/*     */ import java.util.Date;
/*     */ import java.util.TimeZone;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class RolloverManager
/*     */ {
/*  50 */   private static Log mLog = LogFactory.getLog(RolloverManager.class);
/*     */   private RedoLogManager mRedoLogMgr;
/*     */   private File mRedoLogFile;
/*     */   private long mSequence;
/*     */   private static final String ARCH_FILENAME_PREFIX = "redo-";
/*     */   private static final String TEMP_FILENAME_PREFIX = "~tmp-redo-";
/*     */   private static final String SEQUENCE_PREFIX = "-seq";
/*     */   private static final String FILENAME_SUFFIX = ".log";
/*     */   private static final String TIMESTAMP_FORMAT = "yyyyMMdd.HHmmss.SSS";
/*     */   
/*     */   public RolloverManager(RedoLogManager redoLogMgr, File redolog) {
/*  61 */     this.mRedoLogMgr = redoLogMgr;
/*  62 */     this.mRedoLogFile = redolog;
/*  63 */     this.mSequence = 0L;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public void crashRecovery()
/*     */     throws IOException
/*     */   {
/*  71 */     File[] logs = this.mRedoLogFile.getParentFile().listFiles(new TempLogFilenameFilter(null));
/*  72 */     if (logs.length > 0) {
/*  73 */       FileUtil.sortFilesByModifiedTime(logs);
/*     */       
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*  80 */       if (!this.mRedoLogFile.exists()) {
/*  81 */         File mostRecent = logs[(logs.length - 1)];
/*  82 */         String name = mostRecent.getName();
/*  83 */         String currName = this.mRedoLogFile.getName();
/*  84 */         if (mostRecent.renameTo(this.mRedoLogFile)) {
/*  85 */           mLog.info("Renamed " + name + " to " + currName);
/*     */         } else {
/*  87 */           throw new IOException("Unable to rename " + name + " to " + currName);
/*     */         }
/*  89 */         logs[(logs.length - 1)] = null;
/*     */       }
/*     */       
/*     */ 
/*     */ 
/*     */ 
/*  95 */       int numErrors = 0;
/*  96 */       for (int i = 0; (i < logs.length) && (logs[i] != null); i++) {
/*  97 */         File log = logs[i];
/*  98 */         String oldName = log.getName();
/*  99 */         String newName = oldName + ".bak";
/* 100 */         File newLog = new File(log.getParentFile(), newName);
/* 101 */         if (log.renameTo(newLog)) {
/* 102 */           mLog.info("Renamed " + oldName + " to " + newName);
/*     */         } else {
/* 104 */           numErrors++;
/* 105 */           mLog.error("Unable to rename " + oldName + " to " + newName);
/*     */         }
/*     */       }
/*     */       
/* 109 */       if (numErrors > 0) {
/* 110 */         throw new IOException("Error(s) occurred while renaming temporary redo log files");
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static File[] getArchiveLogs(File archiveDir)
/*     */   {
/* 122 */     return getArchiveLogs(archiveDir, Long.MIN_VALUE, Long.MAX_VALUE);
/*     */   }
/*     */   
/*     */   public static File[] getArchiveLogs(File archiveDir, long from) {
/* 126 */     return getArchiveLogs(archiveDir, from, Long.MAX_VALUE);
/*     */   }
/*     */   
/*     */   public static File[] getArchiveLogs(File archiveDir, long from, long to) {
/* 130 */     File[] logs = archiveDir.listFiles(new FilenameFilter() {
/*     */       public boolean accept(File dir, String name) {
/* 132 */         if ((name.indexOf("redo-") == 0) && (name.lastIndexOf(".log") == name.length() - ".log".length()))
/*     */         {
/* 134 */           long seq = RolloverManager.getSeqForFile(new File(dir, name));
/* 135 */           if ((this.val$from <= seq) && (seq <= this.val$to))
/* 136 */             return true;
/*     */         }
/* 138 */         return false;
/*     */       }
/*     */     });
/* 141 */     if ((logs != null) && (logs.length > 0))
/* 142 */       sortArchiveLogFiles(logs);
/* 143 */     return logs;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static void sortArchiveLogFiles(File[] files)
/*     */   {
/* 152 */     ArchiveLogFilenameComparator comp = new ArchiveLogFilenameComparator(null);
/* 153 */     Arrays.sort(files, comp);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   private static class ArchiveLogFilenameComparator
/*     */     implements Comparator<File>
/*     */   {
/*     */     public int compare(File f1, File f2)
/*     */     {
/* 164 */       long t1 = RolloverManager.getSeqForFile(f1);
/* 165 */       long t2 = RolloverManager.getSeqForFile(f2);
/* 166 */       if (t1 < t2)
/* 167 */         return -1;
/* 168 */       if (t1 > t2) {
/* 169 */         return 1;
/*     */       }
/*     */       
/* 172 */       t1 = RolloverManager.getEndTimeForFile(f1);
/* 173 */       t2 = RolloverManager.getEndTimeForFile(f2);
/* 174 */       if (t1 < t2)
/* 175 */         return -1;
/* 176 */       if (t1 > t2)
/* 177 */         return 1;
/* 178 */       return 0;
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   public static long getSeqForFile(File f)
/*     */   {
/* 185 */     String fname = f.getName();
/* 186 */     int start = fname.lastIndexOf("-seq");
/* 187 */     if (start == -1) return -1L;
/* 188 */     start += "-seq".length();
/* 189 */     int end = fname.indexOf(".log", start);
/* 190 */     if (end == -1) return -1L;
/*     */     try {
/* 192 */       String val = fname.substring(start, end);
/* 193 */       return Long.parseLong(val);
/*     */     } catch (StringIndexOutOfBoundsException se) {
/* 195 */       return -1L;
/*     */     } catch (NumberFormatException ne) {}
/* 197 */     return -1L;
/*     */   }
/*     */   
/*     */   public static long getEndTimeForFile(File f)
/*     */   {
/* 202 */     DateFormat fmt = new SimpleDateFormat("yyyyMMdd.HHmmss.SSS");
/* 203 */     fmt.setLenient(false);
/* 204 */     int prefixLen = "redo-".length();
/*     */     try {
/* 206 */       Date d = fmt.parse(f.getName().substring(prefixLen));
/* 207 */       return d.getTime();
/*     */     } catch (ParseException e) {}
/* 209 */     return f.lastModified();
/*     */   }
/*     */   
/*     */   public static String toArchiveLogFilename(Date date, long seq)
/*     */   {
/* 214 */     StringBuilder fname = new StringBuilder("redo-");
/* 215 */     DateFormat fmt = new SimpleDateFormat("yyyyMMdd.HHmmss.SSS");
/* 216 */     fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
/* 217 */     fname.append(fmt.format(date));
/* 218 */     fname.append("-seq").append(seq);
/* 219 */     fname.append(".log");
/*     */     
/* 221 */     return fname.toString();
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   private static class TempLogFilenameFilter
/*     */     implements FilenameFilter
/*     */   {
/*     */     public boolean accept(File dir, String name)
/*     */     {
/* 232 */       if ((name.indexOf("~tmp-redo-") == 0) && (name.lastIndexOf(".log") == name.length() - ".log".length()))
/*     */       {
/* 234 */         return true;
/*     */       }
/* 236 */       return false;
/*     */     }
/*     */   }
/*     */   
/*     */   public File getRolloverFile(long seq) {
/* 241 */     String fname = toArchiveLogFilename(new Date(), seq);
/* 242 */     File destDir = this.mRedoLogMgr.getRolloverDestDir();
/* 243 */     if (!destDir.exists())
/*     */     {
/*     */ 
/* 246 */       if ((!destDir.mkdir()) && (!destDir.exists())) {
/* 247 */         mLog.error("Unable to create rollover destination directory " + destDir.getAbsolutePath());
/*     */       }
/*     */     }
/* 250 */     return new File(destDir, fname);
/*     */   }
/*     */   
/*     */   public String getTempFilename(long seq) {
/* 254 */     StringBuilder fname = new StringBuilder("~tmp-redo-");
/* 255 */     DateFormat fmt = new SimpleDateFormat("yyyyMMdd.HHmmss.SSS");
/* 256 */     fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
/* 257 */     fname.append(fmt.format(new Date()));
/* 258 */     fname.append("-seq").append(seq);
/* 259 */     fname.append(".log");
/*     */     
/* 261 */     return fname.toString();
/*     */   }
/*     */   
/*     */   public synchronized long getCurrentSequence() {
/* 265 */     return this.mSequence;
/*     */   }
/*     */   
/*     */   public synchronized void initSequence(long seq) {
/* 269 */     this.mSequence = seq;
/*     */   }
/*     */   
/*     */   public synchronized long incrementSequence() {
/* 273 */     if (this.mSequence < Long.MAX_VALUE) {
/* 274 */       this.mSequence += 1L;
/*     */     } else
/* 276 */       this.mSequence = 0L;
/* 277 */     return this.mSequence;
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/redolog/RolloverManager.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */